use crate::src::struct_and_type::{
    ArrayList, ArrayListCompareFunc, ArrayListEqualFunc, ArrayListValue,
};

extern "C" {
    fn malloc(_: u64) -> *mut ();
    fn realloc(_: *mut (), _: u64) -> *mut ();
    fn free(_: *mut ());
    fn memmove(_: *mut (), _: *const (), _: u64) -> *mut ();
}
#[no_mangle]
pub extern "C" fn arraylist_new(mut length: u32) -> *mut ArrayList {
    let mut new_arraylist: *mut ArrayList = 0 as *mut ArrayList;
    if length <= 0 as u32 {
        length = 16 as u32;
    }
    new_arraylist =
        (unsafe { malloc(::core::mem::size_of::<ArrayList>() as u64) }) as *mut ArrayList;
    if new_arraylist.is_null() {
        return 0 as *mut ArrayList;
    }
    (unsafe { (*new_arraylist)._alloced = length });
    (unsafe { (*new_arraylist).length = 0 as u32 });
    (unsafe {
        (*new_arraylist).data =
            malloc((length as u64).wrapping_mul(::core::mem::size_of::<ArrayListValue>() as u64))
                as *mut ArrayListValue
    });
    if (unsafe { (*new_arraylist).data }).is_null() {
        (unsafe { free(new_arraylist as *mut ()) });
        return 0 as *mut ArrayList;
    }
    return new_arraylist;
}
#[no_mangle]
pub extern "C" fn arraylist_free(mut arraylist: *mut ArrayList) {
    if !arraylist.is_null() {
        (unsafe { free((*arraylist).data as *mut ()) });
        (unsafe { free(arraylist as *mut ()) });
    }
}
extern "C" fn arraylist_enlarge(mut arraylist: *mut ArrayList) -> i32 {
    let mut data: *mut ArrayListValue = 0 as *mut ArrayListValue;
    let mut newsize: u32 = 0;
    newsize = (unsafe { (*arraylist)._alloced }).wrapping_mul(2 as i32 as u32);
    data = (unsafe {
        realloc(
            (*arraylist).data as *mut (),
            (::core::mem::size_of::<ArrayListValue>() as u64).wrapping_mul(newsize as u64),
        )
    }) as *mut ArrayListValue;
    if data.is_null() {
        return 0;
    } else {
        (unsafe { (*arraylist).data = data });
        (unsafe { (*arraylist)._alloced = newsize });
        return 1;
    };
}
#[no_mangle]
pub extern "C" fn arraylist_insert(
    mut arraylist: *mut ArrayList,
    mut index: u32,
    mut data: ArrayListValue,
) -> i32 {
    if index > (unsafe { (*arraylist).length }) {
        return 0;
    }
    if (unsafe { (*arraylist).length }).wrapping_add(1 as i32 as u32)
        > (unsafe { (*arraylist)._alloced })
    {
        if arraylist_enlarge(arraylist) == 0 {
            return 0;
        }
    }
    (unsafe {
        memmove(
            &mut *((*arraylist).data).offset(index.wrapping_add(1 as i32 as u32) as isize)
                as *mut ArrayListValue as *mut (),
            &mut *((*arraylist).data).offset(index as isize) as *mut ArrayListValue
                as *const (),
            (((*arraylist).length).wrapping_sub(index) as u64)
                .wrapping_mul(::core::mem::size_of::<ArrayListValue>() as u64),
        )
    });
    let fresh0 = unsafe { &mut (*((*arraylist).data).offset(index as isize)) };
    *fresh0 = data;
    (unsafe { (*arraylist).length = ((*arraylist).length).wrapping_add(1) });
    (unsafe { (*arraylist).length });
    return 1;
}
#[no_mangle]
pub extern "C" fn arraylist_append(mut arraylist: *mut ArrayList, mut data: ArrayListValue) -> i32 {
    return arraylist_insert(arraylist, unsafe { (*arraylist).length }, data);
}
#[no_mangle]
pub extern "C" fn arraylist_prepend(
    mut arraylist: *mut ArrayList,
    mut data: ArrayListValue,
) -> i32 {
    return arraylist_insert(arraylist, 0 as u32, data);
}
#[no_mangle]
pub extern "C" fn arraylist_remove_range(
    mut arraylist: *mut ArrayList,
    mut index: u32,
    mut length: u32,
) {
    if index > (unsafe { (*arraylist).length })
        || index.wrapping_add(length) > (unsafe { (*arraylist).length })
    {
        return;
    }
    (unsafe {
        memmove(
            &mut *((*arraylist).data).offset(index as isize) as *mut ArrayListValue
                as *mut (),
            &mut *((*arraylist).data).offset(index.wrapping_add(length) as isize)
                as *mut ArrayListValue as *const (),
            (((*arraylist).length).wrapping_sub(index.wrapping_add(length)) as u64)
                .wrapping_mul(::core::mem::size_of::<ArrayListValue>() as u64),
        )
    });
    (unsafe { (*arraylist).length = ((*arraylist).length).wrapping_sub(length) });
}
#[no_mangle]
pub extern "C" fn arraylist_remove(mut arraylist: *mut ArrayList, mut index: u32) {
    arraylist_remove_range(arraylist, index, 1 as u32);
}
#[no_mangle]
pub extern "C" fn arraylist_index_of(
    mut arraylist: *mut ArrayList,
    mut callback: ArrayListEqualFunc,
    mut data: ArrayListValue,
) -> i32 {
    let mut i: u32 = 0;
    i = 0 as u32;
    while i < (unsafe { (*arraylist).length }) {
        if (unsafe {
            callback.expect("non-null function pointer")(
                *((*arraylist).data).offset(i as isize),
                data,
            )
        }) != 0
        {
            return i as i32;
        }
        i = i.wrapping_add(1);
        i;
    }
    return -(1 as i32);
}
#[no_mangle]
pub extern "C" fn arraylist_clear(mut arraylist: *mut ArrayList) {
    (unsafe { (*arraylist).length = 0 as u32 });
}
extern "C" fn arraylist_sort_internal(
    mut list_data: *mut ArrayListValue,
    mut list_length: u32,
    mut compare_func: ArrayListCompareFunc,
) {
    let mut pivot: ArrayListValue = core::ptr::null_mut();
    let mut tmp: ArrayListValue = core::ptr::null_mut();
    let mut i: u32 = 0;
    let mut list1_length: u32 = 0;
    let mut list2_length: u32 = 0;
    if list_length <= 1 as u32 {
        return;
    }
    pivot = unsafe { *list_data.offset(list_length.wrapping_sub(1 as i32 as u32) as isize) };
    list1_length = 0 as u32;
    i = 0 as u32;
    while i < list_length.wrapping_sub(1 as i32 as u32) {
        if (unsafe {
            compare_func.expect("non-null function pointer")(*list_data.offset(i as isize), pivot)
        }) < 0
        {
            tmp = unsafe { *list_data.offset(i as isize) };
            let fresh1 = unsafe { &mut (*list_data.offset(i as isize)) };
            *fresh1 = unsafe { *list_data.offset(list1_length as isize) };
            let fresh2 = unsafe { &mut (*list_data.offset(list1_length as isize)) };
            *fresh2 = tmp;
            list1_length = list1_length.wrapping_add(1);
            list1_length;
        }
        i = i.wrapping_add(1);
        i;
    }
    list2_length = list_length
        .wrapping_sub(list1_length)
        .wrapping_sub(1 as i32 as u32);
    let fresh3 =
        unsafe { &mut (*list_data.offset(list_length.wrapping_sub(1 as i32 as u32) as isize)) };
    *fresh3 = unsafe { *list_data.offset(list1_length as isize) };
    let fresh4 = unsafe { &mut (*list_data.offset(list1_length as isize)) };
    *fresh4 = pivot;
    arraylist_sort_internal(list_data, list1_length, compare_func);
    arraylist_sort_internal(
        unsafe { &mut *list_data.offset(list1_length.wrapping_add(1 as i32 as u32) as isize) },
        list2_length,
        compare_func,
    );
}
#[no_mangle]
pub extern "C" fn arraylist_sort(
    mut arraylist: *mut ArrayList,
    mut compare_func: ArrayListCompareFunc,
) {
    arraylist_sort_internal(
        unsafe { (*arraylist).data },
        unsafe { (*arraylist).length },
        compare_func,
    );
}
